{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. 2D cylinder flow模型简介\n",
    "【[圆柱绕流](https://baike.baidu.com/item/%E5%9C%86%E6%9F%B1%E7%BB%95%E6%B5%81/4949598?fr=aladdin)】是指二维圆柱低速定常绕流的流型只与Re数有关。在Re≤1时，流场中的惯性力与粘性力相比居次要地位，圆柱上下游的流线前后对称，阻力系数近似与Re成反比(阻力系数为10~60)，此Re数范围的绕流称为斯托克斯区；随着Re的增大，圆柱上下游的流线逐渐失去对称性。\n",
    "\n",
    "![](https://ai-studio-static-online.cdn.bcebos.com/cad237431534419ba2c771727a2e0c9a5be0f0c75ddb4ab49245ff8321014b16)\n",
    "\n",
    "                    --------摘自《神奇的流体》，宫华胜"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. 模型效果及应用场景\n",
    "##  2.1. 背景介绍\n",
    "简单引入科学计算概念以及CFD领域相关概念，同时模型效果预览如下（基于PINN的流场结果为AI for Science结果）\n",
    "* 基于CFD专业软件OpenFoam的流场水平速度\n",
    "![](https://ai-studio-static-online.cdn.bcebos.com/8c5b6a6eed6a405990ecf069103c5133e3969246b2e3417ba6649d43e1751a22)\n",
    "\n",
    "* 基于PINN的流场水平速度\n",
    "![](https://ai-studio-static-online.cdn.bcebos.com/7a3748202dad42878e053b03fddab1f1627d5d5c9bf348e78c17cc62751fd5f8)\n",
    "\n",
    "### 2.1.1. 科学计算\n",
    "\n",
    "【AI For Science】当前AI技术在CV、NLP等领域已有了较为广泛的应用，替代传统方法完成缺陷检测、人脸检测、物体分割、阅读理解、文本生成等任务，在产业界也形成了规模化的落地。但是放眼到更加广阔的工业设计、制造等领域，仍有诸多科学和工程问题亟待解决。比如对于高层建筑结构、大跨桥梁、海上石油平台、航空飞机等，流体和结构的复杂相互作用会引起动力荷载，进而导致抖振、涡振、驰振、颤振等流致振动，影响结构安全与服役年限。数值模拟是研究工程结构流致振动的有效方法之一，但是传统数值方法需要大量的计算资源，在计算速度上有很大的局限性等等。\n",
    "\n",
    "在科学计算领域，往往需要针对海洋气象、能源材料、航空航天、生物制药等具体场景中的物理问题进行模拟。由于大多数物理规律可以表达为偏微分方程的形式，所以偏微分方程组的求解成为了解决科学计算领域问题的关键。神经网络具备“万能逼近”的能力，即只要网络有足够多的神经元，就可以充分地逼近任意一个连续函数。所以使用AI方法解决科学计算问题的一个思路是训练神经网络以模拟某个偏微分方程组的解函数。\n",
    "\n",
    "详见[飞桨加速CFD（计算流体力学）原理与实践](https://mp.weixin.qq.com/s/pQtyKNOH2g-pyO7AqMuQmw)\n",
    "\n",
    "\n",
    "【飞桨科学计算工具组件PaddleScience】旨在加速求解高维的数学物理方程，综合数学计算和物理数据的处理方法，提供数据驱动以及物理机理约束的深度学习求解模型，解决CFD/CAE等多物理场跨尺度模拟的难点。现提供泛化的微分方程、PINNs（物理信息神经网络）和FNO（傅立叶神经算子）等求解器，并提供圆柱绕流、涡激振动等典型计算流体力学案例。综合应用AI与数据结合的科学研究新范式，突破传统科学计算面临的维数高、时间长、跨尺度的挑战，提升智能制造系统设计、建模仿真、分析优化等技术。\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "相信大家能看到这里的一定也是行业内的专家，关于这些流体的基础概念本文就不做多说了。\n",
    "\n",
    "###  2.1.2. PINN方法\n",
    "\n",
    "【PINN】基于物理信息的神经网络 （Physics Informed Neural Network，简称PINN） 是一种科学机器在传统数值领域的应用方法，特别是用于解决与偏微分方程 （PDE） 相关的各种问题，包括方程求解、参数反演、模型发现、控制与优化等。\n",
    "\n",
    "其实，简单点说就是在AI中神经网络多了我们物理学科中的控制方程作为约束，并将我们之前CFD中求解的时空信息，作为训练点，在使**网络输出尽可能的符合初边值与控制方程约束的过程中不断优化网络**。这个网络就是我们拟合的CFD求解器。\n",
    "\n",
    "这种想法不是近年才有的，但是确实是随着深度学习的发展逐渐应用到了CFD或者传统的物理仿真上。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  3. 模型如何使用\n",
    "基于深度学习，采用PINN方法求解圆柱绕流问题主要由以下几步构成，前提是我们需要借助一个比较成熟的深度学习框架，当然我一定会用百度的[PaddlePaddle](https://www.paddlepaddle.org.cn/)框架🤣，事实证明也是比较nice的。\n",
    "\n",
    "百度飞桨框架提供了自动微分、多类算子以及比较广泛的API。同时百度同学基于飞桨框架，开发了一套开源的科学计算套件[PaddleScience](https://github.com/PaddlePaddle/PaddleScience)，里面提供了一些基础的DEMO,也为大家后期进行深一步的工程探索提供了良好的条件。\n",
    "![](https://ai-studio-static-online.cdn.bcebos.com/dd7ec9aeeef94ad9bad3768f370a8ded9e9e86dc9ec841cebc50a339adff1e71)\n",
    "\n",
    "\n",
    "言归正传，接下来给搭建step by step的介绍本项目的实现流程。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  3.1. 环境配置\n",
    "###  3.1.1. 安装Paddle-gpu-develop\n",
    "在进行AI求解圆柱绕流问题前，我们需要先明确深度学习的框架以及科学计算套件等环境。需要注意的是：\n",
    "* 当前PaddleScience套件所应用的深度学习框架为Paddle2.3.2版本，可详见[paddle安装](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/develop/install/pip/linux-pip.html)\n",
    "\n",
    "对于当前示例运行环境，安装代码如下：\n",
    "```\n",
    "!python -m pip install paddlepaddle-gpu==2.3.2.post101 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html\n",
    "```\n",
    "\n",
    "###  3.1.2. 安装PaddleScience及依赖项\n",
    "可从git克隆到目标路径，同时也可以下载后upload.\n",
    "cd至PaddleScience路径，安装依赖项，基于本示例，代码如下：\n",
    "\n",
    "```\n",
    "%cd ~/work/PaddleScience_CubeDomain/refactor_PaddleScience_0430/\n",
    "!pip install -r requirements.txt\n",
    "```\n",
    "\n",
    "### 3.1.3. 环境变量定义\n",
    "代码示意如下：\n",
    "```\n",
    "%env PYTHONPATH=/home/aistudio/work/PaddleScience_CubeDomain/refactor_PaddleScience_0430\n",
    "```\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "import paddle\n",
    "!paddle --version"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "!python -m pip install paddlepaddle-gpu==2.3.2.post101 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html\n",
    "%cd ~/work/PaddleScience_CubeDomain/refactor_PaddleScience_0430/\n",
    "!pip install -r requirements.txt\n",
    "%env PYTHONPATH=/home/aistudio/work/PaddleScience_CubeDomain/refactor_PaddleScience_0430"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "环境配置完成后，log部分示意如下：\n",
    "![](https://ai-studio-static-online.cdn.bcebos.com/843466c039794e21a17beaeec45c02e2e9e7500fbdf2401c961a682d1be3e380)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": []
   },
   "source": [
    "##  3.2. 数据集导入\n",
    "\n",
    "神经网络的训练过程需要大量的训练数据集，我们将CFD计算中的时间t, 空间(x, y）作为训练集对网络进行训练，本案例采用了半监督的方式，即基于部分CFD计算的结果来监督网络的训练过程（目的也是加速网络的收敛，后期逐渐开放结果）\n",
    "\n",
    ">本项目直接将openfoam中定义的网格信息作为神经网络的训练点，并使用load_cfd_data模块加载数据\n",
    "\n",
    "结合CFD求解，训练数据同样也会按照初始值、边界条件、流体域内空间点等进行区分，分别定义了如下分类数据，数据保存在./data_0430文件夹下：\n",
    "* 域内训练点：\n",
    ">domain_train ----流体域内\n",
    "\n",
    "* 边界训练点：\n",
    "当前采用了速度入口、压力出口以及无滑移圆柱边界，并以Re=100进行分析，以下数据用于评估bc_loss.\n",
    ">domain_inlet ----流体域入口              \n",
    ">domain_outlet ----流体域出口                    \n",
    ">domain_cylinder ----圆柱周边\n",
    "\n",
    "* 初始值：\n",
    "采样相对初始时刻作为0时刻，从openfoam提取部分位置的流场信息作为神经网络的初始值监督结果，数据保存在./data_0430/initial文件夹下，用于评估ic_loss.\n",
    "\n",
    "\n",
    "同时，也从openfoam中提取了流场某些关键位置的速度、压力信息等作为网络训练的监督数据。数据保存在./data_0430/probe文件夹下。\n",
    " \n",
    "\n",
    "数据加载可采用如下模块实现：\n",
    "![](https://ai-studio-static-online.cdn.bcebos.com/52bd00787a1547269cde66230d2d4455edc16d1091b341918002007757cad60d)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  3.3. 模型训练\n",
    "\n",
    "基于数据导入模块、网络及训练定义模块等，可直接运行2d_unsteady_cylinder_train.py执行圆柱绕流模型的训练。\n",
    "针对该示例，在V100-32G GPU显卡上，预估训练100000次左右（8h+)能够得到比较理想的结果。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "!python examples/cylinder/2d_unsteady_cylinder_train.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "训练过程log部分示意：\n",
    "![](https://ai-studio-static-online.cdn.bcebos.com/ffc6273e1f284493970d2690ce667dec2a4e593b714e42678199e5c727549c62)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": []
   },
   "source": [
    "##  3.4. 模型预测\n",
    "结合训练完成后保存的网络，直接进行一次前向计算，即可得到训练过程中所有时刻的结果，只需执行如下代码，生成的结果会保存在vtk文件夹中，可通过paraview打开。\n",
    "```\n",
    "!python examples/cylinder/2d_unsteady_cylinder_predict.py\n",
    "```\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "!python examples/cylinder/2d_unsteady_cylinder_predict.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3.5. 精度分析\n",
    "针对PINN中计算的流场结果，与OpenFoam结果对比如下：\n",
    "![](https://ai-studio-static-online.cdn.bcebos.com/04b6593bcc9443f5b7a605d1fb1719e7f9d5dc37e32a4a26ab4b31f6f0e5248a)\n",
    "\n",
    "\n",
    "从对比结果可知，基于AI方式求解的cfd圆柱绕流模型，在大部分区域结果精度已经非常高。\n",
    "但在个别位置，如边界层上则相对误差较大。由于边界层一直是流体中比较复杂的问题，也说明了AI For CFD还有很大的改进空间。\n",
    "\n",
    "\n",
    "***以上，欢迎各位AI+Science的小伙伴探讨交流并加入飞桨科学计算的[共创计划](http://www.paddlepaddle.org.cn/science)，也非常欢迎大家基于飞桨框架以及飞桨科学计算组件探索以及共享一些更有价值的DEMO!***\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  4. 模型原理\n",
    "##  4.1. 物理抽象\n",
    "\n",
    "* 给定计算域内的圆柱绕流\n",
    "边界条件：\n",
    "\n",
    "|边界|类型|\n",
    "| -------- | ------ |\n",
    "| 入口| 速度入口 |\n",
    "| 出口 | 零压 |\n",
    "| 圆柱与上下壁面 | 无滑移 |\n",
    "\n",
    "* 初始值：\n",
    "\n",
    "计算域内采用相对初始时刻的流场信息，相对初始时刻可选择流场稳定的某一时刻\n",
    "\n",
    "\n",
    "![](https://ai-studio-static-online.cdn.bcebos.com/4b050e64262f4d86b5099c70f3cdf5e62c2ec5e787d64e28b0079f2e7d9ea66f)\n",
    "\n",
    "##  4.2. 物性参数定义\n",
    "本示例针对不可压缩流体，并采用2D非定常时间连续方式的流体连续性方程以及动量方程作为控制方程。\n",
    "模型中圆柱半径为1，针对Re=100的工况，定义入口流速为1，可调节粘度定义为2e-2。无量纲化的N-S方程示意如下：\n",
    "\n",
    "##  4.3. 控制方程（损失函数）\n",
    "![](https://ai-studio-static-online.cdn.bcebos.com/aa303caf72c54029a6c21340c31e7791d10a4b2c585e4091aaa92e40f32b6fa0)\n",
    "\n",
    "\n",
    "同时，按照速度入口、压力出口、无滑移圆柱边界等定义边界条件，并定义初始流场信息为相对0时刻，即流场稳定建立后的某一个相对时刻。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "##  4.4. 神经网络\n",
    "\n",
    "采用PINN的方法，并选择FCNet作为深度学习的神经网络，定义代码如下，并在Train模块中直接调用即可。\n",
    "```\n",
    "PINN = psolver.PysicsInformedNeuralNetwork(\n",
    "        layers=6, nu=2e-2, bc_weight=10, eq_weight=1, ic_weight=10, supervised_data_weight=10, \n",
    "        outlet_weight=1, training_type='half-supervised', net_params=net_params)\n",
    "```\n",
    "\n",
    "本示例采用Adam优化器求解，关于超参数的定义如下所示：\n",
    "```\n",
    "adm_opt = psci.optimizer.Adam(learning_rate=1e-4, weight_decay=0.9,parameters=PINN.net.parameters())\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "py35-paddle1.2.0"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "toc-autonumbering": true
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
